package com.top.art.exception;

import com.alibaba.fastjson.JSONException;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.top.art.vo.ResVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * The type Global exception handler.
 *
 * @author hjh
 * @version 2020 /10/5-19:56
 */
@Slf4j
@ControllerAdvice
@Order(-1)
public class GlobalExceptionHandler {


    private static final String ERROR_CODE = "errorCode";

    /**
     * 拦截业务异常
     *
     * @param e the e
     * @return the res vo
     */
    @ExceptionHandler(ArtException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResVO<Object> notFount(ArtException e) {
        if (e.getCode() == null) {
            e.setCode(5000);
        }
        printBusinessException(e);
        return new ResVO<>(e.getCode(), e.getMessage());
    }

    /**
     * 参数格式转换错误
     *
     * @param e the e
     * @return the res vo
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResVO<Object> httpMessageNotReadableException(HttpMessageNotReadableException e) {
        log.info(String.format("入参格式错误[%s]", ERROR_CODE + 5001), e);
        return new ResVO<>(5001, "入参格式错误");
    }

    /**
     * 参数类型转换错误
     *
     * @param e the e
     * @return the res vo
     */
    @ExceptionHandler(InvalidFormatException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResVO<Object> invalidFormatException(InvalidFormatException e) {
        log.info(String.format("类型错误[%s]", ERROR_CODE + 5002), e);
        return new ResVO<>(5002, "参数类型转换错误");
    }

    /**
     * json转换错误
     *
     * @param e the e
     * @return the res vo
     */
    @ExceptionHandler(JSONException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResVO<Object> jsonExceptionException(JSONException e) {
        log.info(String.format("json解析错误[%s]", ERROR_CODE + 5003), e);
        return new ResVO<>(5003, "json解析错误");
    }

    /**
     * 拦截入参错误
     *
     * @param e the e
     * @return the res vo
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResVO<Object> paramsException(MethodArgumentNotValidException e) {
        log.info(String.format("入参错误[%s]", ERROR_CODE + 5004), e);
        BindingResult bindingResult = e.getBindingResult();
        return new ResVO<>(5004, bindingResult.getAllErrors().get(0).getDefaultMessage());
    }


    /**
     * Http media type not supported exception res vo.
     *
     * @param e the e
     * @return the res vo
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResVO<Object> httpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        log.warn(String.format("无效的ContentType[%s]", ERROR_CODE + 5005), e);
        return new ResVO<>(5005, "无效的ContentType");
    }

    /**
     * 拦截未知系统错误
     *
     * @param e the e
     * @return the res vo < object
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public ResVO<Object> systemError(Exception e) {
        log.info(String.format("系统错误[%s]", ERROR_CODE + 5006), e);
        return new ResVO<>(5006, "系统错误");
    }

    private void printBusinessException(ArtException e) {
        log.info("[{}]: {}",  e.getCode(), e.getMessage());
    }

}
